/*--------------------------------------------------------------------------------------------------
Yatak Operation System Project Copyright 2012
Author : Ilya Churaev
Started : 3 May 2012		Updated : 4 May 2012
File Name : libc.c		Purpose : library
--------------------------------------------------------------------------------------------------*/

#include <stddef.h>
#include <stdarg.h>
#include <vsprintf.h>

#define SYSCALL(num, argv, argc)\
	({\
		int ret;\
		asm volatile("int $0x30;":"=a"(ret):"a"(num),"b"((void*)argv),"c"(argc));\
		ret;\
	})

static void* syscall(int num, void *argv, int argc)
{
	int ret;
	__asm__ volatile("int $0x30;":"=a"(ret):"a"(num),"b"(argv),"c"(argc));
	return (void*)ret;
}

int write(int fd, const void *buffer, int buffLen)
{
	void volatile *argv[]={(void*)fd, (void*)buffer, (void*)buffLen};
	return (int)syscall(0,argv,sizeof(argv)/sizeof(void*));
}

int lread(int fd, const void *buffer, int buffLen)
{
	void volatile *argv[]={(void*)fd, (void*)buffer, (void*)buffLen};
	return (int)syscall(1,argv,sizeof(argv)/sizeof(void*));
}

int create_process(const char *path, const char *arg0, ...)
{
	void *argv[32];
	va_list args;
	const char *curr;
	int count;

	argv[0] = (void*)path;

	for(count=0, curr=arg0, va_start(args, arg0); curr; curr = va_arg(args, const char*), count++)
		argv[count+1]=(void*)curr;
	va_end(args);

	return (int)syscall(2,argv,count+1);
}

int do_exit(int status)
{
	return syscall(4, 0, 0);
}

int wait(int pid)
{
	void volatile *argv[]={(void*)pid};
	return (int)syscall(5, argv, sizeof(argv)/sizeof(void*));
}


/* WRAP AROUND */

#define MAX_LINE_SIZE 1024
int _printf(const char *fmt, ...)
{
	char buffer[MAX_LINE_SIZE];
	va_list args;
	int i;

	va_start(args, fmt);
	i=vsprintf(buffer,fmt,args);
	va_end(args);

	if(i>=0)
		write(STDOUT, buffer, i);

	return i;
}

int _scanf(const char *fmt, ...)
{
	char buffer[MAX_LINE_SIZE];
	va_list args;
	int i;

	if(lread(STDIN, buffer,MAX_LINE_SIZE)>0)
	{
		va_start(args, fmt);
		i=vsscanf(buffer,fmt,args);
		va_end(args);
		return i;
	}
	else
		return 0;
}

char *gets(char *str)
{
	int count = lread(STDIN, str, MAX_LINE_SIZE);
	return (count>0) ? str : 0;
}

char *puts(char *str)
{
	write(STDOUT, str, MAX_LINE_SIZE);
	return str;
}

